iT邦幫忙

2022 iThome 鐵人賽

DAY 10
1
自我挑戰組

跟著 Go 實戰聖經 一起自學 Go系列 第 10

DAY 10 Go 語言 迴圈的使用

  • 分享至 

  • xImage
  •  

昨天學習在 Go 語言中 if ... else 及 switch...case 的條件判斷,今天就進入到迴圈的懷抱吧!

迴圈是什麼?

我之前曾做過秘書,每個月的月初都是我的惡夢,因為要協助計算員工薪水,其實計算的公式就是固定的,但每個月每人的業績一定不可能一樣,所以我總是花很多時間,在一一重複計算那些不屬於我的錢錢,啊如果是算我自己的薪水,我大概會樂此不疲,在我學習到迴圈之後,覺得曾經的我真的是太年輕了,迴圈是可以把需要重複執行的某些程式,根據你給他的輸入重複執行,且輸出結果,所以意思是我寫好計算公式,把大家的業績丟進去,然後去吃個下午茶,回來薪水會自己算好在我面前。用一個很有畫面的切身之痛,來告訴大家迴圈是多方便的好東西。

for 迴圈

for 迴圈通常是用來處理有序的集合,如:1 加到 100。先來看看使用方式,再來一一解釋吧!

for <起始賦值敘述>; <條件敘述>; <結束敘述> {
    <程式碼區塊>
}
  1. 起始賦值敘述:相信大家並不陌生,沒錯就是跟 if 及 switch 一樣的敘述,可以是簡單的敘述,且會在其他敘述開始前先執行
  2. 條件敘述:會在迴圈每次執行前檢查,條件成立就執行迴圈,條件不成立就停止。如:i > 5 ,那今天若 i := 6 那迴圈便會繼續執行;若是 i := 3 那迴圈便會停止執行。
  3. 結束敘述:會在迴圈跑完每圈後執行,最常用來遞增或是遞減,如:i++。
  4. 程式碼區塊:便是我想要重複執行的事。

上面是最標準的 for 迴圈,但其實省略部分的 for 迴圈也是可以的,以下示範幾個簡化的寫法

省略起始賦值敘述、條件敘述及結束敘述

for {
    <程式碼區塊>
}

三者都省略,等同於 for true 就會一直執行,而這樣會造成無窮迴圈,若想終止這個 for 迴圈,需要加上 break ,來跳出無窮迴圈。

除了條件敘述其餘省略

for <條件敘述> {
    <程式碼區塊>
}

此種 for 迴圈,較常用在讀取資料,如: 資料庫、檔案或 API 等等,從資料傳回的布林值,來判斷迴圈結束與否,所以我們並不用另外給予起始賦值敘述或結束敘述。

若是長度不確定或是沒有順序的資料

for <鍵>, <值> := range <集合> {
    <程式碼區塊>
}

一開始介紹時有說過 for 迴圈通常是用來處理有序的集合,故若是遇到這種沒有順序的資料,如:映射表(maps),我們會改用 range 敘述,在後面章節會有對於 map 的詳細介紹,這邊只需要先知道有這個寫法。

for i 迴圈

我們經常使用 i( = 索引值 index ) 來作為 for 迴圈內的變數(當然你想要取名為 abc 也是可以的,但我們不太會取這種意義不明的名字),而這個 i 變數的作用範圍 scope 是只有存在於 for 迴圈內的,此種迴圈很適合用來處理用數字作為索引的有序集合,如:陣列、切片等等,以下示範使用 for 迴圈,一般累加變數及切片元素。

範例 1:

package main

import "fmt"

func main(){
    for i := 1; i <= 5; i++{
        fmt.Println(i)
    }
}

範例 1(執行結果):

1
2
3
4
5

範例 2:

package main

import "fmt"

func main(){
    favoriteFruit := []string{"apple","kiwi","peach","mango"}

    for i := 0; i < len(favoriteFruit); i++ { // len() 可以取得任意集合的長度,索引值從 0 起累加,用 len() 的回傳值即可判定迴圈是否走到最後一個值,是否繼續執行或是終止。
        fmt.Println(favoriteFruit[i])
    }
}

範例 2(執行結果):

apple
kiwi
peach
mango

?補充:
若 len() 回傳集合長度為 N ,則該集合的最後一個元素即為 N-1。

for range 迴圈

在範例二我們試著用 for 迴圈走訪有序的切片,像是切片或是陣列裡的索引值都是有順序的從 0 開始,但在 map 裡就不一樣,因為 map 的鍵 (key) 與值 (value) 並不會按照順序排列,如果我們使用 for i 迴圈,因為不是按照順序的,是會拿取到錯誤順序的資料,所以這時就需要 range 。 range 是每次從集合取出一個鍵 (key) 與值 (value) ,而下一輪迴圈就換下一組,且在使用 range 敘述時,不需要結束敘述,因為在取完集合的所有值,便會自動結束迴圈。

?補充:
map 中元素是隨機排列的,本是為了防止開發人員仰賴元素順序來取值,但反過來說,你也可以使用 map 來模擬資料隨機排序。

範例 3:

package main

import "fmt"

func main(){
    myFavorite := map[string]string{
        "fruit":"mango",
        "animal":"panda",
        "dessert":"cheesecake"
    }

    for key, value := range myFavorite{
        fmt.Println("key:",key," = value:",value)
    }
}

範例 3(執行結果):

key: fruit  = value: mango
key: animal  = value: panda
key: dessert  = value: cheesecake

?補充:
在 range 中,若不需要用到 key, value 是都可以省略的,只需要改成底線字元 _ 或直接省略即可。

範例 4:

package main

import "fmt"

func main(){
    myFavorite := map[string]string{
        "fruit":"mango",
        "animal":"panda",
        "dessert":"cheesecake"
    }

    for _, value := range myFavorite { // key 因為不需要用到,改成 _
        fmt.Println(value)
    }
}

範例 4(執行結果):

mango
panda
cheesecake

範例 5:

package main

import "fmt"

func main(){
    myFavorite := map[string]string{
        "fruit":"mango",
        "animal":"panda",
        "dessert":"cheesecake"
    }

    for key := range myFavorite{ // value 沒有需要用掉,可直接省略,或等同於 for key, _ := range myFavorite
        fmt.Println(key)
    }
}

範例 5(執行結果):

fruit
animal
dessert

?補充:
range 敘述也可以用於陣列或切片,此時 key 會是索引值, value 是元素值,這樣一來就跟 for i 的效果相同,且不用自己計算長度,以及程式碼會變得簡潔,唯一的缺點是無法使用 map 來修改原集合的 value,因為 value 是在迴圈中建立的變數,跟外面的原集合是沒有關係的。

範例 6:

package main

import "fmt"

func main(){
    favoriteFruit := []string{"apple","kiwi","peach","mango"}

    for i , value := range favoriteFruit{
        fmt.Println("index:",i,"value:",value)
    }
}

範例 6(執行結果):

index: 0 value: apple
index: 1 value: kiwi
index: 2 value: peach
index: 3 value: mango

break 和 continue 敘述

用 break 來中止迴圈,完全離開迴圈

上面有說到的,若是不小心寫出無窮迴圈,我們需要直接讓這個迴圈停止,這時便可以使用 break 來終止迴圈並跳出,當然也可以寫一個判斷,在特定狀況下跳出迴圈。

用 continue 來中止迴圈,並進入新的一輪迴圈

continue 跟 break 的差別就在於,符合判斷的 continue 會終止這輪迴圈,然後再進入新的下一輪的迴圈。

範例 7:

package main

import (
	"fmt"
	"math/rand"
)

func main(){
    for{
        i := rand.Intn(10) // 產生 0~10 的亂數
        if i%3 == 0 { // 若是 3 的倍數
            fmt.Println("i=",i,",用 continue 來跳過這次迴圈")
            continue
        } else if i%2 == 0 { // 若是 2 的倍數
            fmt.Println("i=",i,",用 break 來終止這次迴圈")
            break
        }
        fmt.Println("i=",i)
    }
}

範例 7(執行結果):

i= 1
i= 7
i= 7
i= 9 ,用 continue 來跳過這次迴圈
i= 1
i= 8 ,用 break 來終止這次迴圈

這裡我們省略起始賦值敘述、條件敘述及結束敘述的 for 無窮 迴圈,但是加上 continue 和 break,限制這個無窮迴圈,便可以讓這個迴圈有終止。

今天學習到了在 Go 語言中的迴圈,明天繼續來介紹 Go 語言中有哪些核心型別吧!


上一篇
DAY 9 Go 語言 條件判斷 - switch 敘述
下一篇
DAY 11 Go 語言 的核心型別 - 數字
系列文
跟著 Go 實戰聖經 一起自學 Go30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言